home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 12 / Example 12.2 / app.cpp next >
Encoding:
C/C++ Source or Header  |  2006-08-01  |  9.6 KB  |  367 lines

  1. //////////////////////////////////////////////////////////////
  2. // Example 12.2: Fireball!                                    //
  3. // Written by: C. Granberg, 2006                            //
  4. //////////////////////////////////////////////////////////////
  5.  
  6. #include <windows.h>
  7. #include <d3dx9.h>
  8. #include "debug.h"
  9. #include "skinnedmesh.h"
  10. #include "shader.h"
  11. #include "effect.h"
  12. #include "mesh.h"
  13.  
  14. class APPLICATION
  15. {
  16.     public:
  17.         APPLICATION();
  18.         HRESULT Init(HINSTANCE hInstance, int width, int height, bool windowed);
  19.         HRESULT Update(float deltaTime);
  20.         HRESULT Render();
  21.         HRESULT Cleanup();
  22.         HRESULT Quit();
  23.         DWORD FtoDword(float f){return *((DWORD*)&f);}
  24.         void SetAnimation(char name[]);
  25.  
  26.     private:
  27.         IDirect3DDevice9* m_pDevice; 
  28.         D3DLIGHT9 m_light;        
  29.         HWND m_mainWindow;
  30.         ID3DXFont *m_pFont;
  31.  
  32.         //Meshes
  33.         MESH m_target;
  34.         MESHINSTANCE m_targetInstance;
  35.         TRANSFORM m_magicianTrans;
  36.         SKINNEDMESH m_skinnedMesh;
  37.         ID3DXAnimationController* m_pAnimControl;
  38.         bool m_attack;
  39.         float m_attackTime, m_deltaTime;
  40.  
  41.         //Shaders
  42.         SHADER m_unitVS, m_unitPS;
  43.         D3DXHANDLE m_worldHandle, m_viewProjHandle, m_sunHandle, m_teamColHandle;
  44.  
  45.         //Effects 
  46.         std::vector<EFFECT*> m_effects;
  47. };
  48.  
  49. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int showCmd)
  50. {
  51.     APPLICATION app;
  52.  
  53.     if(FAILED(app.Init(hInstance, 800, 600, true)))return 0;
  54.  
  55.     MSG msg;
  56.     memset(&msg, 0, sizeof(MSG));
  57.     int startTime = timeGetTime(); 
  58.  
  59.     while(msg.message != WM_QUIT)
  60.     {
  61.         if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
  62.         {
  63.             ::TranslateMessage(&msg);
  64.             ::DispatchMessage(&msg);
  65.         }
  66.         else
  67.         {    
  68.             int t = timeGetTime();
  69.             float deltaTime = (t - startTime)*0.001f;
  70.  
  71.             app.Update(deltaTime);
  72.             app.Render();
  73.  
  74.             startTime = t;
  75.         }
  76.     }
  77.  
  78.     app.Cleanup();
  79.  
  80.     return msg.wParam;
  81. }
  82.  
  83. APPLICATION::APPLICATION()
  84. {
  85.     m_pDevice = NULL; 
  86.     m_mainWindow = 0;
  87.     srand(GetTickCount());
  88.     m_attack = false;
  89. }
  90.  
  91. HRESULT APPLICATION::Init(HINSTANCE hInstance, int width, int height, bool windowed)
  92. {
  93.     debug.Print("Application initiated");
  94.  
  95.     //Create Window Class
  96.     WNDCLASS wc;
  97.     memset(&wc, 0, sizeof(WNDCLASS));
  98.     wc.style         = CS_HREDRAW | CS_VREDRAW;
  99.     wc.lpfnWndProc   = (WNDPROC)::DefWindowProc; 
  100.     wc.hInstance     = hInstance;
  101.     wc.lpszClassName = "D3DWND";
  102.  
  103.     //Register Class and Create new Window
  104.     RegisterClass(&wc);
  105.     m_mainWindow = CreateWindow("D3DWND", "Example 12.2: Fireball!", WS_EX_TOPMOST, 0, 0, width, height, 0, 0, hInstance, 0); 
  106.     SetCursor(NULL);
  107.     ShowWindow(m_mainWindow, SW_SHOW);
  108.     UpdateWindow(m_mainWindow);
  109.  
  110.     //Create IDirect3D9 Interface
  111.     IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
  112.  
  113.     if(d3d9 == NULL)
  114.     {
  115.         debug.Print("Direct3DCreate9() - FAILED");
  116.         return E_FAIL;
  117.     }
  118.  
  119.     //Check that the Device supports what we need from it
  120.     D3DCAPS9 caps;
  121.     d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
  122.  
  123.     //Hardware Vertex Processing or not?
  124.     int vp = 0;
  125.     if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
  126.         vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  127.     else vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  128.  
  129.     //Check vertex & pixelshader versions
  130.     if(caps.VertexShaderVersion < D3DVS_VERSION(2, 0) || caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
  131.     {
  132.         debug.Print("Warning - Your graphic card does not support vertex and pixelshaders version 2.0");
  133.     }
  134.  
  135.     //Set D3DPRESENT_PARAMETERS
  136.     D3DPRESENT_PARAMETERS d3dpp;
  137.     d3dpp.BackBufferWidth            = width;
  138.     d3dpp.BackBufferHeight           = height;
  139.     d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
  140.     d3dpp.BackBufferCount            = 1;
  141.     d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
  142.     d3dpp.MultiSampleQuality         = 0;
  143.     d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
  144.     d3dpp.hDeviceWindow              = m_mainWindow;
  145.     d3dpp.Windowed                   = windowed;
  146.     d3dpp.EnableAutoDepthStencil     = true; 
  147.     d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
  148.     d3dpp.Flags                      = 0;
  149.     d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
  150.     d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;
  151.  
  152.     //Create the IDirect3DDevice9
  153.     if(FAILED(d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_mainWindow,
  154.                                  vp, &d3dpp, &m_pDevice)))
  155.     {
  156.         debug.Print("Failed to create IDirect3DDevice9");
  157.         return E_FAIL;
  158.     }
  159.  
  160.     //Release IDirect3D9 interface
  161.     d3d9->Release();
  162.  
  163.     // Create m_light
  164.     ::ZeroMemory(&m_light, sizeof(m_light));
  165.     m_light.Type      = D3DLIGHT_DIRECTIONAL;
  166.     m_light.Ambient   = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  167.     m_light.Diffuse   = D3DXCOLOR(0.9, 0.9, 0.9, 1.0f);
  168.     m_light.Specular  = D3DXCOLOR(0.5, 0.5, 0.5, 1.0f);
  169.     m_light.Direction = D3DXVECTOR3(0.0f, -1.0f, 0.0f);
  170.     m_pDevice->SetLight(0, &m_light);
  171.     m_pDevice->LightEnable(0, true);
  172.  
  173.     LoadEffectResources(m_pDevice);
  174.  
  175.     D3DXCreateFont(m_pDevice, 18, 0, 0, 1, false,  
  176.                    DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  177.                    DEFAULT_PITCH | FF_DONTCARE, "Arial", &m_pFont);
  178.  
  179.     m_skinnedMesh.Load("units/magician.x", m_pDevice);
  180.     m_pAnimControl = m_skinnedMesh.GetAnimationControl();
  181.     SetAnimation("Still");
  182.  
  183.     m_target.Load("meshes/target.x", m_pDevice);
  184.     m_targetInstance.SetMesh(&m_target);
  185.  
  186.     //Position objects
  187.     m_targetInstance.SetPosition(D3DXVECTOR3(15.0f, 0.0f, 40.0f));
  188.     m_targetInstance.SetRotation(D3DXVECTOR3(0.0f, 0.6f, 0.0f));
  189.     m_targetInstance.SetScale(D3DXVECTOR3(0.7f, 0.7f, 0.7f));
  190.  
  191.     m_magicianTrans.Init(D3DXVECTOR3(-5.0f, 0.0f, -10.0f), D3DXVECTOR3(0.0f, D3DX_PI + 0.4f, 0.0f), D3DXVECTOR3(1.0f, 1.0f, 1.0f));
  192.  
  193.     //Set sampler state
  194.     for(int i=0;i<4;i++)
  195.     {
  196.         m_pDevice->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  197.         m_pDevice->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  198.         m_pDevice->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
  199.     }
  200.  
  201.     //Setup shaders
  202.     m_unitVS.Init(m_pDevice, "shaders/lighting.vs", VERTEX_SHADER);
  203.     m_worldHandle = m_unitVS.GetConstant("matW");
  204.     m_viewProjHandle = m_unitVS.GetConstant("matVP");
  205.     m_sunHandle = m_unitVS.GetConstant("DirToSun");
  206.  
  207.     m_unitPS.Init(m_pDevice, "shaders/teamCol.ps", PIXEL_SHADER);
  208.     m_teamColHandle = m_unitPS.GetConstant("tmCol");
  209.  
  210.     return S_OK;
  211. }
  212.  
  213. HRESULT APPLICATION::Update(float deltaTime)
  214. {
  215.     //Remove dead effects
  216.     std::vector<EFFECT*>::iterator i;
  217.     for(i=m_effects.begin();i != m_effects.end();)
  218.     {
  219.         if((*i)->isDead())
  220.         {
  221.             delete (*i);
  222.             m_effects.erase(i);
  223.         }
  224.         else 
  225.         {
  226.             (*i)->Update(deltaTime);
  227.             i++;
  228.         }
  229.     }
  230.  
  231.     //Control attack animation
  232.     if(m_attack)
  233.     {
  234.         m_attackTime += deltaTime * 0.3f;
  235.         m_deltaTime = deltaTime * 0.3f;
  236.         if(m_attackTime >= 0.40f)
  237.         {
  238.             SetAnimation("Still");
  239.             m_attack = false;
  240.             m_attackTime = 0.0f;
  241.         }
  242.     }
  243.     else m_deltaTime = 0.0f;
  244.  
  245.     //Keayboard input
  246.     if(KEYDOWN(VK_SPACE))
  247.     {
  248.         if(m_effects.empty())
  249.         {
  250.             m_effects.push_back(new EFFECT_FIREBALL(m_pDevice, m_skinnedMesh.FindBone("Staff"), m_targetInstance.m_pos + D3DXVECTOR3(-0.3f, 3.5f, -0.5f)));
  251.             SetAnimation("Attack");
  252.             m_attack = true;
  253.             m_attackTime = 0.0f;
  254.         }
  255.     }
  256.     if(KEYDOWN(VK_RETURN))
  257.     {
  258.         if(m_effects.empty())
  259.             m_effects.push_back(new EFFECT_SPELL(m_pDevice, m_magicianTrans.m_pos));
  260.     }
  261.     else if(KEYDOWN(VK_ESCAPE))
  262.     {
  263.         Quit();
  264.     }
  265.  
  266.     return S_OK;
  267. }    
  268.  
  269. HRESULT APPLICATION::Render()
  270. {
  271.     // Clear the viewport
  272.     m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  273.  
  274.     //Set camera
  275.     D3DXMATRIX view, proj, world, identity;
  276.     D3DXMatrixLookAtLH(&view, &D3DXVECTOR3(0.0f, 20.0f, -50.0f), &D3DXVECTOR3(0.0f, 3.0f, 0.0f), &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
  277.     D3DXMatrixPerspectiveFovLH(&proj, 0.4f, 1.33333f, 0.01f, 1000.0f);
  278.     world = m_magicianTrans.GetWorldMatrix();
  279.     D3DXMatrixIdentity(&identity);
  280.  
  281.     m_pDevice->SetTransform(D3DTS_VIEW, &view);
  282.     m_pDevice->SetTransform(D3DTS_PROJECTION, &proj);
  283.     m_pDevice->SetTransform(D3DTS_WORLD, &identity);
  284.  
  285.     // Begin the scene 
  286.     if(SUCCEEDED(m_pDevice->BeginScene()))
  287.     {
  288.         m_unitVS.SetMatrix(m_worldHandle, identity);
  289.         m_unitVS.SetMatrix(m_viewProjHandle, view * proj);
  290.  
  291.         D3DXVECTOR3 sun;
  292.         D3DXVec3Normalize(&sun, &D3DXVECTOR3(0.5f, 1.0f, -0.5));
  293.         m_unitVS.SetVector3(m_sunHandle, sun);
  294.  
  295.         m_unitPS.SetVector4(m_teamColHandle, D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f));
  296.  
  297.         m_unitVS.Begin();
  298.         m_unitPS.Begin();
  299.         m_skinnedMesh.SetPose(world, m_pAnimControl, m_deltaTime);
  300.         m_skinnedMesh.Render(NULL);
  301.         m_unitPS.End();
  302.         m_unitVS.End();
  303.  
  304.         m_pDevice->SetRenderState(D3DRS_LIGHTING, true);
  305.         m_targetInstance.Render();
  306.  
  307.         //Render Effects
  308.         for(int i=0;i<m_effects.size();i++)
  309.             if(m_effects[i] != NULL)
  310.                 m_effects[i]->Render();
  311.  
  312.         if(m_effects.empty())
  313.         {
  314.             RECT r[] = {{10, 10, 0, 0}, {10, 30, 0, 0}};
  315.             m_pFont->DrawText(NULL, "Space: Throw Fireball", -1, &r[0], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  316.             m_pFont->DrawText(NULL, "Return: Cast Spell", -1, &r[1], DT_LEFT| DT_TOP | DT_NOCLIP, 0xffffffff);
  317.         }
  318.         // End the scene.
  319.         m_pDevice->EndScene();
  320.         m_pDevice->Present(0, 0, 0, 0);
  321.     }
  322.  
  323.     return S_OK;
  324. }
  325.  
  326. HRESULT APPLICATION::Cleanup()
  327. {
  328.     try
  329.     {
  330.         UnloadEffectResources();
  331.  
  332.         m_target.Release();
  333.  
  334.         m_pFont->Release();
  335.         m_pDevice->Release();
  336.  
  337.         debug.Print("Application terminated");
  338.     }
  339.     catch(...){}
  340.  
  341.     return S_OK;
  342. }
  343.  
  344. HRESULT APPLICATION::Quit()
  345. {
  346.     ::DestroyWindow(m_mainWindow);
  347.     ::PostQuitMessage(0);
  348.     return S_OK;
  349. }
  350.  
  351. void APPLICATION::SetAnimation(char name[])
  352. {
  353.     ID3DXAnimationSet *anim = NULL;
  354.  
  355.     for(int i=0;i<m_pAnimControl->GetMaxNumAnimationSets();i++)
  356.     {
  357.         anim = NULL;
  358.         m_pAnimControl->GetAnimationSet(i, &anim);
  359.  
  360.         if(anim != NULL)
  361.         {
  362.             if(strcmp(name, anim->GetName()) == 0)
  363.                 m_pAnimControl->SetTrackAnimationSet(0, anim);
  364.             anim->Release();
  365.         }
  366.     }
  367. }